/*            Copyright(c) 2006-2008 Dave Sexton           *
 * http://www.codeplex.com/DocProject                      *
 * http://www.codeplex.com/DocProject/Project/License.aspx *
 ***********************************************************/
using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;
using System.Xml.XPath;
using System.ComponentModel.Design;

namespace DaveSexton.DocProject.Sandcastle.BuildComponents.TypeConverters.BuiltIn
{
	internal sealed class SharedContentComponentTypeConverter : TypeConverter
	{
		#region Public Properties
		#endregion

		#region Private / Protected
		#endregion

		#region Constructors
		/// <summary>
		/// Constructs a new instance of the <see cref="SharedContentComponentTypeConverter" /> class.
		/// </summary>
		public SharedContentComponentTypeConverter()
		{
		}
		#endregion

		#region Methods
		private IEnumerable<IXPathNavigable> GetContentElementFiles(IXPathNavigable navigable)
		{
			if (navigable != null)
			{
				XPathNavigator navigator = navigable.CreateNavigator();

				foreach (XPathNavigator node in navigator.SelectChildren("content", string.Empty))
				{
					if (node.MoveToAttribute("file", "") && node.Value.Trim().Length > 0)
						yield return node;
				}
			}
		}

		public override bool GetPropertiesSupported(ITypeDescriptorContext context)
		{
			return true;
		}

		public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes)
		{
			PropertyDescriptorCollection properties = new PropertyDescriptorCollection(null);

			int i = 0;
			foreach (IXPathNavigable file in GetContentElementFiles(value as IXPathNavigable))
				properties.Add(new ContentPropertyDescriptor("Content" + i++, file, context));

			return properties;
		}

		public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
		{
			if (destinationType == typeof(string))
			{
				List<IXPathNavigable> files = new List<IXPathNavigable>(GetContentElementFiles(value as IXPathNavigable));

				return string.Format(System.Globalization.CultureInfo.CurrentCulture, Resources.Text.SharedContentComponentPropertyValue, files.Count);
			}
			else
				return base.ConvertTo(context, culture, value, destinationType);
		}
		#endregion

		#region Nested
		private sealed class ContentPropertyDescriptor : PropertyDescriptor
		{
			#region Public Properties
			public override Type ComponentType
			{
				get
				{
					return context.PropertyDescriptor.ComponentType;
				}
			}

			public override bool IsReadOnly
			{
				get
				{
					return false;
				}
			}

			public override Type PropertyType
			{
				get
				{
					return typeof(string);
				}
			}

			public override string DisplayName
			{
				get
				{
					return displayName;
				}
			}

			public override string Description
			{
				get
				{
					return string.Format(System.Globalization.CultureInfo.CurrentCulture,
						Resources.Text.SharedContentComponentDescription, file.Value);
				}
			}
			#endregion

			#region Private / Protected
			private readonly XPathNavigator file;
			private readonly string displayName, defaultFile;
			private readonly ITypeDescriptorContext context;
			#endregion

			#region Constructors
			/// <summary>
			/// Constructs a new instance of the <see cref="ContentPropertyDescriptor" /> class.
			/// </summary>
			public ContentPropertyDescriptor(string name, IXPathNavigable file, ITypeDescriptorContext context)
				: base(name, new Attribute[] { new NotifyParentPropertyAttribute(true) })
			{
				this.file = file.CreateNavigator();
				this.context = context;

				defaultFile = this.file.Value;
				displayName = CreateDisplayName(defaultFile);
			}
			#endregion

			#region Methods
			private static string CreateDisplayName(string file)
			{
				Uri uri;
				if (Uri.TryCreate(Environment.ExpandEnvironmentVariables(file), UriKind.RelativeOrAbsolute, out uri))
					return System.IO.Path.GetFileName((uri.IsAbsoluteUri) ? uri.LocalPath : System.Web.HttpUtility.UrlDecode(uri.ToString()));
				else
					return file;
			}

			public override bool ShouldSerializeValue(object component)
			{
				return !string.Equals(file.Value, defaultFile, StringComparison.OrdinalIgnoreCase);
			}

			public override bool CanResetValue(object component)
			{
				return true;
			}

			public override void ResetValue(object component)
			{
				file.SetValue(defaultFile);
			}

			public override object GetValue(object component)
			{
				return file.Value;
			}

			public override void SetValue(object component, object value)
			{
				file.SetValue((string) value);
			}
			#endregion
		}
		#endregion
	}
}
